# coding: utf-8

import itertools

import Pcl4Curve as pc
from PSOFT.PshItertools import flatten
from PSOFT.vendor.Qt_py.Qt import QtCore, QtGui, QtWidgets

class BezierCurve():

    def __init__(self):
        self.pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.GlobalColor.white))
        self.pen.setWidth(15)
        self.curvePath = QtGui.QPainterPath()
        self.stroker = QtGui.QPainterPathStroker()
        self.stroker.setWidth(15)

    def hitTest(self, curveModels, width, height, point):
        if not self.drawCurve(curveModels, width, height):
            return True

        stroke = self.stroker.createStroke(self.curvePath)
        return stroke.contains(point)

    def drawCurve(self, curveModels, width, height):
        curveSegments = self.handlesToSegments(curveModels)
        self.curvePath = QtGui.QPainterPath()
        if not curveSegments:
            return None

        for segment in curveSegments:
            segmentCoords = [(x * width, y * height) for (x, y) in segment]
            head = segmentCoords[0]
            tail = itertools.islice(segmentCoords, 1, None)
            flatTail = flatten(tail)
            self.curvePath.moveTo(*head)
            if len(segmentCoords) == 2:
                self.curvePath.lineTo(*flatTail)
            elif len(segmentCoords) == 3:
                self.curvePath.quadTo(*flatTail)
            elif len(segmentCoords) == 4:
                self.curvePath.cubicTo(*flatTail)
        return self.curvePath

    def handlesToSegments(self, _curveModels):
        newSegments = []
        for curr, prev, _ in _curveModels.iter():
            if not prev:
                newSegments.append(((0.0, curr.cp.y), curr.cp,))
                continue
            oneSegment = []
            if prev.handleType == pc.HANDLE_LINEAR:
                oneSegment.append(prev.cp)
            else:
                h = prev.getModifiedHandleOut(curr)
                oneSegment.extend((prev.cp, h))

            if curr.handleType == pc.HANDLE_LINEAR:
                oneSegment.append(curr.cp)
            else:
                h = curr.getModifiedHandleIn(prev)
                oneSegment.extend((h, curr.cp))

            newSegments.append(oneSegment)
        else:
            if newSegments:
                newSegments.append((curr.cp, (1.0, curr.cp.y)))

        return newSegments

    def getCurve(self, curveModels):
        curve = pc.CCurve()

        for c1, c0, _ in curveModels.iter():
            if not c0:
                curve.addNodeL(c1.cp.x - 1e-9,  c1.cp.y, c1.cp.x,  c1.cp.y)
                continue

            if c0.handleType == pc.HANDLE_LINEAR \
               and c1.handleType == pc.HANDLE_LINEAR:
                curve.addNodeL(c0.cp.x, c0.cp.y, c1.cp.x, c1.cp.y)
            else:
                x0, y0 = c0.cp.x, c0.cp.y
                x1, y1 = c0.getModifiedHandleOut(c1)
                x2, y2 = c1.getModifiedHandleIn(c0)
                x3, y3 = c1.cp.x, c1.cp.y

                curve.addNodeB(x0, y0, x1, y1, x2, y2, x3, y3)
        else:
            if curve.rowCount():
                curve.addNodeL(c1.cp.x + 1e-9,  c1.cp.y, c1.cp.x,  c1.cp.y)

        return curve
